package logique.calculateur;

import java.util.ArrayList;
import java.util.LinkedList;

import logique.reseau.Troncon;
import logique.reseau.Ville;

/**
 * L'idée est de choisir aléatoirement l'enchainement des étapes et de lancer un dijkstra
 * dans chacun des cas.
 * 
 * @author root
 *
 */
public class BruteForce extends Initialisation{
	
	/**
	 * Algorithme de recherche d'un chemin satisfaisant les étapes
	 * 
	 * @return Le chemin souhaité sous la forme d'une pile d'entiers
	 */
	public Itineraire calcule(){
		Itineraire i1 = calculeSens();
		
		Ville depart = prefs.getVilleArrivee();
		prefs.setVilleArrivee(prefs.getVilleDepart());
		prefs.setVilleDepart(depart);
		
		Itineraire i2 = calculeSens();
		
		depart = prefs.getVilleArrivee();
		prefs.setVilleArrivee(prefs.getVilleDepart());
		prefs.setVilleDepart(depart);
		
		if (i1.getScore() < i2.getScore())
			return i1;
		
		return i2.inverse();
		
	}
		
	public Itineraire calculeSens(){

		// Objet Dijkstra utilisé pour les calculs.
		Dijkstra d = new Dijkstra(calculateur); 
		
		LinkedList<Troncon> solution = new LinkedList<Troncon>();
		
		// Morceau de chemin, recoit les résultats des éxecutions du/des Dijkstra
		LinkedList<Troncon> morceau;
		
		ArrayList<Ville> etapes = new ArrayList<Ville>(prefs.getEtapesObligatoires().getEtapes());
		
		/*
		 * On cherche le plus court chemin du départ vers la plus proche des étapes
		 * (ville d'arrivée exclue) jusqu'à ce qu'il n'y en ait plus. On calcule le
		 * pcc vers la ville d'arrivée en dernier.
		 */
		
		Ville courante = prefs.getVilleDepart();
		
		while ( !etapes.isEmpty() ){
			
			morceau = d.calculPCC(courante, etapes, prefs);
			
			etapes.remove(courante);
			
			courante = d.getLastVille();

			// On est sur que les morceaux sont entrés dans l'ordre
			solution.addAll(morceau);
			
		}

		// PCC vers l'�tape d'arrivée
		solution.addAll(d.calculPCC(courante, prefs.getVilleArrivee(), prefs));
		
		// calcul de l'itineraire trouvé

		Itineraire itineraire = new Itineraire(prefs.getVilleDepart(), solution);

		if( activeVoisines ){
			villesVoisines = new LinkedList<Ville>();
			for (Troncon troncon : solution) {
				for (Troncon t : troncon.getVille1().getTroncons()) {
					if( !villesVoisines.contains(t.getVille1()) ){
						villesVoisines.add(t.getVille1());
					}
					if( !villesVoisines.contains(t.getVille2()) ){
						villesVoisines.add(t.getVille2());
					}
				}
				for (Troncon t : troncon.getVille2().getTroncons()) {
					if( !villesVoisines.contains(t.getVille1()) ){
						villesVoisines.add(t.getVille1());
					}
					if( !villesVoisines.contains(t.getVille2()) ){
						villesVoisines.add(t.getVille2());
					}
				}
			}
		}
		
		return itineraire;
	}


	/* (non-Javadoc)
	 * @see logique.calculateur.Algorithme#getInitialisation()
	 */
	@Override
	public Initialisation getInitialisation() {
		return null;
	}
}
